package cn.felord.authorization.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.util.FileCopyUtils;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * 资源进行token拦截器应该提前执行 避免被匿名处理造成deny 具体看 application配置文件  security.oauth2.resource.filter-order=3
 *
 * @author dax.
 * @version v1.0
 * @since 2018/1/8 14:27
 */
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    /**
     * 如果是资源分离设置 需要导入公钥   converter.setVerifierKey(publicKey)
     */
    private static JwtAccessTokenConverter jwtAccessTokenConverter() {
        JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter() {
            /***
             * 重写增强token方法,用于自定义一些token返回的信息
             */
            @Override
            public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
                String userName = authentication.getUserAuthentication().getName();

                User user = (User) authentication.getUserAuthentication().getPrincipal();

                final Map<String, Object> additionalInformation = new HashMap<>();
                additionalInformation.put("userName", userName);
                additionalInformation.put("roles", user.getAuthorities());
                ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInformation);
                return super.enhance(accessToken, authentication);
            }
        };
//       设置公钥   分离配置  需要 解析公钥文件    参见JwtAccessTokenConverter 源码  153行 154  实现即可
        ClassPathResource resource = new ClassPathResource("public.cer");
        try {
            String publicKey = new String(FileCopyUtils.copyToByteArray(resource.getInputStream()));
            accessTokenConverter.setVerifierKey(publicKey);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return accessTokenConverter;
    }


    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
        resources.resourceId(ResourceConstant.DEFAULT_RESOURCE);
//        只做校验
        JwtTokenStore  jwtTokenStore=new JwtTokenStore(jwtAccessTokenConverter());

        resources.tokenStore(jwtTokenStore);
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
                // Since we want the protected resources to be accessible in the UI as well we need
                // session creation to be allowed (it's disabled by default in 2.0.6)
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
                .and()
                .requestMatchers().anyRequest()
                .and()
                .anonymous()
                .and()
                .authorizeRequests()
//                    .antMatchers("/product/**").access("#oauth2.hasScope('select') and hasRole('ROLE_USER')")
                .antMatchers("/user/**").authenticated();//配置order访问控制，必须认证过后才可以访问
/*        http.requestMatcher(new OAuth2RequestedMatcher()).anonymous().and()
                .authorizeRequests()
                .antMatchers(HttpMethod.OPTIONS).permitAll()
                .anyRequest().authenticated();*/
    }



}
